Skip to content

feat: add an opt-in Node FFI PTY experiment - #1018

Open
John-David Dalton (jdalton) wants to merge 1 commit into
microsoft:mainfrom
jdalton:experiment/ffi-pty
Open

John-David Dalton (jdalton) wants to merge 1 commit into
microsoft:mainfrom
jdalton:experiment/ffi-pty

Conversation

@jdalton

@jdalton John-David Dalton (jdalton) commented Nov 11, 2026 •

Copy link
Copy Markdown

Adds an opt-in PTY backend using Node's built-in FFI. It leaves node-pty's public entry point, API, and npm package unchanged.

The package-size proposals, #1015 and #1016, both compress the .node assets to address #864. #1015 keeps them together in the existing package; #1016 distributes them in platform-specific packages. This PR tests a different backend.

Packaging the experiment separately, including compiled Windows x64 and ARM64 helpers, gives this size comparison:

Published node-pty Standalone FFI experiment Saved
Packed 7.15 MB 0.17 MB 6.99 MB
Unpacked 26.91 MB 0.42 MB 26.49 MB
Size measurement

Compared node-pty 1.2.0-beta.18 with all prebuilds against an archive containing the experiment scripts, README, license, minimal package manifest, and both compiled Windows helpers from CI. Launcher source is excluded; binaries are unsigned. Signing adds overhead. Sizes use decimal MB and savings are calculated before rounding.

Measured archives: 7,152,900 vs. 166,739 bytes packed; 26,907,504 vs. 415,460 bytes unpacked. This models standalone distribution; this PR's existing npm package still excludes the experiment.

Platform behavior
  • Windows builds 17763–26099 default to a Node subprocess. The native helper is used only after Authenticode verifies the configured publisher.
  • Windows build 26100+ uses an in-process FFI worker; this covers Windows 11 24H2+ and Server 2025.
  • macOS uses public APIs and an MTS bootstrap to acquire the controlling terminal.
  • Linux uses glibc 2.34+.

Windows selects the backend with RtlGetVersion and uses a kill-on-close job to clean up the target and its descendants. Requires Node.js 26.12+ on x64 or ARM64. The API is experimental and does not fully implement IPty; credentials, pixel dimensions, bundled ConPTY options, and non-UTF-8 encodings are unsupported.

Optional signed helper

With no publisher configured, Node is used without inspecting the helper. Otherwise, a bounded PE sniff requests at most 110 bytes and never reads the executable payload. A certificate header only triggers full Windows Authenticode verification and an exact publisher check.

Verified helpers stay file-locked to prevent replacement. Missing files, failed verification, or failed startup fall back to Node. CI builds unsigned helpers; this PR does not configure release signing.

Validation

The seven-platform run passed on the implementation before the final comment and test-title cleanup. The current VS Code PR check is pending.

Tests cover terminal I/O, Unicode, arguments, environment and working directory, large input/output, resize, pause/resume, signals, concurrent sessions, cleanup, process crashes, signed-helper verification, and the 110-byte PE sniff limit. The signed-helper integration test runs only on disposable GitHub-hosted Windows runners.

node --experimental-ffi experiments/ffi-pty/probe.mts
node --experimental-ffi --test test/experiments/ffi-pty/*.test.mts

@jdalton John-David Dalton (jdalton) changed the title feat: add an opt-in Node FFI PTY experiment feat: add opt-in Node FFI PTY experiment; related to #864, #1015, #1016 Nov 11, 2026
@jdalton John-David Dalton (jdalton) changed the title feat: add opt-in Node FFI PTY experiment; related to #864, #1015, #1016 feat: add an opt-in Node FFI PTY experiment Nov 11, 2026
@jdalton

Copy link
Copy Markdown
Author

\cc Simon Lydell (@lydell)

@jdalton

Copy link
Copy Markdown
Author

My personal taste would be to use rolldown and bundle it into a dist/ before publish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant